#include"show_bmp.h"

/***************************************
 * 函数功能：显示图片  800*480
 * 函数名：int show_bmp(const char *pathname)
 * 形参：const char *pathname
 * 返回值：int -1失败 0成功
 ***************************************/
int show_bmp(const char *pathname)
{
    int bmp_fd, i,j;
    //存储bmp文件的像素点
    unsigned char bmp_buff[800*480*3] = {0};
    //写进内存映射缓冲区的缓冲区
    unsigned int *buff = malloc(800*480*sizeof(unsigned int)); // 使用动态分配的内存

    if (buff == NULL) 
    {
        perror("malloc error:");
        return -1;
    }

    bmp_fd = open(pathname, O_RDONLY);
    if(bmp_fd == -1)
    {
        perror("open");
        free(buff);
        return -1;
    }

    //跳过54个字节头
    lseek(bmp_fd, 54, SEEK_SET);

    //读图片的全部RGB到缓冲区
    if (read(bmp_fd, bmp_buff, sizeof(bmp_buff)) != sizeof(bmp_buff)) 
    {
        perror("read error:");
        free(buff);
        close(bmp_fd);
        return -1;
    }

    //将RGB转换为BGR
    for(i=0; i<800*480; i++)
    {
        buff[i] = (bmp_buff[3*i+2] << 16) | (bmp_buff[3*i+1] << 8) | bmp_buff[3*i+0];//AGRB
    }

    // 像素点填充到屏幕
    for(i = 0; i < 480; i++) // 按行遍历
    { 
        for(j = 0; j < 800; j++) // 按列遍历
        { 
            // 从buff中获取像素数据，确保使用正确的索引
            unsigned int pixel = buff[i * 800 + j]; //i=0 :0 - 799
            
            // 将像素数据复制到帧缓冲区mem_p中
            // 确保使用正确的索引，这里假设mem_p的布局与buff相同
            mem_p[((479 - i) * 800) + j] = pixel;  //479*800 - 479*800+799
        }
    }

    free(buff);
    close(bmp_fd);
    return 0;
}

/************************************************************************
 * 函数功能：在指定位置显示图片
 * 函数名：int show_bmp_xy(const char *pathname, int start_x, int start_y)
 * 形参：const char *pathname, int start_x, int start_y
 * 返回值：int -1失败 0成功
 *************************************************************************/
int show_bmp_xy(const char *pathname, int start_x, int start_y)
{
    int bmp_fd, x, y, i, j;
 
	// 读取BMP格式头，获取图片信息
	struct bitmap_header header;
	struct bitmap_info info;
	struct rgb_quad quad;
 
    bmp_fd = open(pathname, O_RDWR);
    if(bmp_fd == -1)
    {
        printf("open bmp fail\n");
        return -1;
    }   
 
    // 第一、二个结构体是必有信息
	read(bmp_fd, &header, sizeof(header));
	read(bmp_fd, &info, sizeof(info));
 
    // 第三个结构体是可选的，需要判断是否存在
	if(info.compression != 0)
	{
		read(bmp_fd, &quad, sizeof(quad));
		fprintf(stderr, "read quad! \n");
	}
 
    // 输出图片相关信息
    printf("图片大小: %d\n", header.size);
    printf("图片尺寸: %d×%d\n", info.width, info.height);
    printf("色深: %dbpp\n", info.bit_count);
 
    int width = info.width;
    int height = info.height;
 
    if((start_x+width) > 800  || (start_y+height) > 480)
    {
        printf("图片越界,无法显示\n");
        close(bmp_fd);
        return -1;
    }
 
    //定义存储图片所有RGB数据的缓冲区
    unsigned char *bmp_buff = (unsigned char *)malloc(width*height*3);
    unsigned int *buff = (unsigned int *)malloc(width*height*4);
 
    //将图片的像素存放bmp_buf当
    read(bmp_fd, bmp_buff, width*height*3);
 
    for(i=0; i<width*height; i++)
    {
        buff[i] = bmp_buff[3*i+0]|bmp_buff[3*i+1]<<8|bmp_buff[3*i+2]<<16;
    }   
 
    //像素点填充到屏幕
    for(y=0; y<height; y++)
    {
        for(x=0; x<width; x++) 
        {
            mem_p[(start_y+y)*800+start_x+x] = buff[(height-1-y)*width+x];
        }
    }

 
    free(bmp_buff);
    free(buff);
    close(bmp_fd);
}

/**********
 * 天气界面
***********/
void show_weather(void)
{
    char buff[] = {"多云 25-34 摄氏度"};

    //初始化Lcd
    struct LcdDevice* lcd = init_lcd("/dev/fb0");
                
    //打开字体	
    font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
        
    //字体大小的设置
    fontSetSize(f,20);
            
    //创建一个画板（点阵图）
    bitmap *bm = createBitmapWithInit(120,30,4,getColor(0,255,255,255)); 
        //也可使用createBitmapWithInit函数，改变画板颜色
        // bitmap *bm = createBitmap(288, 100, 4);

    fontPrint(f,bm,0,0,buff,getColor(0,255,0,0),0);

    //把字体框输出到LCD屏幕上
    show_font_to_lcd(lcd->mp,656,428,bm);
        
    //关闭字体，关闭画板
    fontUnload(f);
    destroyBitmap(bm); 
}

/************************************************ 
 * 函数功能：在指定位置播放视频
 * 函数名：void show_mplayer(int *change_dir_index)
 * 形参：int *change_dir_index
 * void
**************************************************/
void show_mplayer(int *change_dir_index)
{
    const char *filename;
    if (change_dir_index == 0)
    {
        filename = "mp4.txt";
    }
    else
    {
        filename = "/mnt/udisk/test/mp4.txt";
    }
    
    Node head = NULL; // 初始化头节点为NULL
    // 从文件加载图片名称
    printf("从文件加载图片名称...\n");
    load_pictures_from_file(&head, filename);
    FILE *fp;
    char command[256];

    // 创建管道
    system("mkfifo pipe");

    // 构建 mplayer 命令
    snprintf(command, sizeof(command), "mplayer -slave -quiet -input file=pipe -geometry 15:150 -zoom -x 600 -y 300 %s", head->filename);

    // 执行命令
    fp = popen(command, "w");
    if (fp == NULL) {
        perror("popen");
        exit(EXIT_FAILURE);
    }

    // 等待命令执行完成
    pclose(fp);

    // 删除管道
    system("rm pipe");
}

/********* 
 * 主页面
**********/
void show_one(void)
{
    lcd_init();
    show_bmp("theme.bmp");
}

/************* 
 * 位置选择界面
***************/
void show_change_location(void)
{
    lcd_init();
    show_bmp("location.bmp");
}

/************ 
 * 密码页面
 ************/
void show_password(void)
{
    lcd_init();
    show_bmp("password.bmp");
    lcd_uninit();
    // char password_buff[] = {"* * * * * *"};

    // //初始化Lcd
    // struct LcdDevice* lcd = init_lcd("/dev/fb0");
                
    // //打开字体	
    // font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
        
    // //字体大小的设置
    // fontSetSize(f,60);
            
    // //创建一个画板（点阵图）
    // bitmap *bm = createBitmapWithInit(300,30,4,getColor(0,255,255,255)); 
    //     //也可使用createBitmapWithInit函数，改变画板颜色
    //     // bitmap *bm = createBitmap(288, 100, 4);

    // fontPrint(f,bm,0,0,buff,getColor(0,255,0,0),0);

    // //把字体框输出到LCD屏幕上
    // show_font_to_lcd(lcd->mp,30,105,bm);
        
    // //关闭字体，关闭画板
    // fontUnload(f);
    // destroyBitmap(bm); 
} 

/************ 
 * 管理员页面
 ************/
void show_user(void)
{
    lcd_init();
    show_bmp("user.bmp");
    lcd_uninit();
}

/*************************************************************** 
 * 函数功能：显示位置页面，可以点击更换地理位置
 * 函数名：void show_location(char *buff[],int *location_data)
 * 形参：char *buff[],int *location_data
 * 返回值：void
 ***************************************************************/
void show_location(char *buff[],int *location_data)
{
    //初始化Lcd
    struct LcdDevice* lcd = init_lcd("/dev/fb0");
                
    //打开字体	
    font *f = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
        
    //字体大小的设置
    fontSetSize(f,25);
            
    //创建一个画板（点阵图）
    bitmap *bm = createBitmapWithInit(120,30,4,getColor(0,255,255,255)); 

    fontPrint(f,bm,0,0,buff[*location_data],getColor(0,255,0,0),0);

    //把字体框输出到LCD屏幕上
    show_font_to_lcd(lcd->mp,658,312,bm);
        
    //关闭字体，关闭画板
    fontUnload(f);
    destroyBitmap(bm); 
}
